package lg.minecraft.plugin.testeconomy.storage.model;

import lg.minecraft.plugin.testeconomy.TestEconomy;
import lg.minecraft.plugin.testeconomy.config.ManiConfig;
import lg.minecraft.plugin.testeconomy.storage.DataBaseStorage;
import lg.minecraft.plugin.testeconomy.storage.StorageType;

import java.sql.*;
import java.util.ArrayList;
import java.util.List;

/**
 * @author langle__
 * @version 1.0
 */
public class MySQLStorage extends DataBaseStorage {

    private Connection connection;

    public MySQLStorage() {
        ManiConfig maniConfig = TestEconomy.getManiConfig();
        String host = maniConfig.getMySqlHost();
        int port = maniConfig.getMySqlPort();
        String database = maniConfig.getMySqlDataBase();
        String user = maniConfig.getMySqlUser();
        String password = maniConfig.getMySqlPassword();
        List<String> args = maniConfig.getMySqlArgList();

        String url = "jdbc:mysql://" + host + ":" + port + "/" + database + (args.isEmpty() ? "" : "?" + String.join("&", args));

        try {
            initConnectionAndTable(url, user, password);
        } catch (SQLException e) {
            try {
                createDbIfNotExists(host, port, user, password, database);
                initConnectionAndTable(url, user, password);
            } catch (SQLException ex) {
                TestEconomy.getInstance().getLogger().warning("Failed to connect to the database: " + e.getMessage());
            }
        }
    }

    /**
     * 初始化数据库连接并创建 Money 表（如果不存在）。
     *
     * @param url      数据库连接 URL
     * @param user     数据库用户名
     * @param password 数据库密码
     * @throws SQLException 如果连接或执行 SQL 出错
     */
    private void initConnectionAndTable(String url, String user, String password) throws SQLException {
        this.connection = DriverManager.getConnection(url, user, password);
        this.connection.setAutoCommit(true);
        try (Statement statement = connection.createStatement()) {
            statement.executeUpdate("CREATE TABLE IF NOT EXISTS money (player_name VARCHAR(255) PRIMARY KEY, amount DOUBLE)");
        }
    }

    /**
     * 检查数据库是否存在，如果不存在则创建它。
     *
     * @param host     数据库主机地址
     * @param port     数据库端口
     * @param user     数据库用户名
     * @param password 数据库密码
     * @param database 要创建的数据库名称
     * @throws SQLException 如果连接或执行 SQL 出错
     */
    private void createDbIfNotExists(String host, int port, String user, String password, String database) throws SQLException {
        try (Connection connection = DriverManager.getConnection("jdbc:mysql://" + host + ":" + port + "/", user, password)) {
            connection.setAutoCommit(true);
            try (Statement statement = connection.createStatement()) {
                statement.executeUpdate("CREATE DATABASE IF NOT EXISTS " + database + " DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;");
            }
        }
    }

    @Override
    public Connection getConnection() {
        return this.connection;
    }

    @Override
    public StorageType getType() {
        return StorageType.MYSQL;
    }

    @Override
    protected Double getMoney(String playerName) {
        String sql = "SELECT amount FROM money WHERE player_name = ?";
        try (PreparedStatement stmt = connection.prepareStatement(sql)) {
            stmt.setString(1, playerName);
            ResultSet rs = stmt.executeQuery();
            if (rs.next()) {
                return rs.getDouble("amount");
            }
        } catch (SQLException e) {
            TestEconomy.getInstance().getLogger().warning("Failed to get money for player: " + playerName);
        }
        return 0.0;
    }

    @Override
    protected void setMoney(String playerName, double amount) {
        String sql = "INSERT INTO money (player_name, amount) VALUES (?, ?) ON DUPLICATE KEY UPDATE amount = ?";
        try (PreparedStatement stmt = connection.prepareStatement(sql)) {
            stmt.setString(1, playerName);
            stmt.setDouble(2, amount);
            stmt.setDouble(3, amount);
            stmt.executeUpdate();
        } catch (SQLException e) {
            TestEconomy.getInstance().getLogger().warning("Failed to set money for player: " + playerName);
        }
    }

    @Override
    protected List<String> getPlayers() {
        String sql = "SELECT player_name FROM money";
        List<String> players = new ArrayList<>();
        try (ResultSet rs = connection.createStatement().executeQuery(sql)) {
            while (rs.next()) {
                players.add(rs.getString("playerName"));
            }
        } catch (SQLException e) {
            TestEconomy.getInstance().getLogger().warning("Failed to retrieve player list from database");
        }
        return players;
    }

}
